package com.ruoyi.waterDistribution.service.impl;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.core.constant.BusinessConstants;
import com.ruoyi.common.core.domain.base.datam.WiOrganB;
import com.ruoyi.common.core.domain.business.waterDistribution.WiCropB;
import com.ruoyi.common.core.domain.business.waterDistribution.WiGetvolM;
import com.ruoyi.common.core.domain.business.waterDistribution.WiOrgplanM;
import com.ruoyi.common.core.domain.business.waterDistribution.WiPeriodY;
import com.ruoyi.common.core.domain.business.waterManagement.WrStatvolM;
import com.ruoyi.common.core.enums.TenEnum;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.business.BusinessUtils;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.waterDistribution.controller.WiOrgplanMController;
import com.ruoyi.waterDistribution.mapper.WiCropBMapper;
import com.ruoyi.waterDistribution.mapper.WiOrgplanMMapper;
import com.ruoyi.waterDistribution.mapper.WiPeriodYMapper;
import com.ruoyi.waterDistribution.service.IWiOrgplanMService;
import com.ruoyi.waterDistribution.vo.WiLandBVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 月机构限额水量及计划水量计算Service业务层处理
 *
 * @author ps
 * @date 2023-02-16
 */
@Service
public class WiOrgplanMServiceImpl implements IWiOrgplanMService {
    private static final Logger log = LoggerFactory.getLogger(WiOrgplanMServiceImpl.class);

    @Autowired
    private WiOrgplanMMapper wiOrgplanMMapper;
    @Autowired
    private WiPeriodYMapper wiPeriodYMapper;

    /**
     * 查询月机构限额水量及计划水量计算
     *
     * @param orgCd 月机构限额水量及计划水量计算主键
     * @return 月机构限额水量及计划水量计算
     */
    @Override
    public WiOrgplanM selectWiOrgplanMByOrgCd(String orgCd) {
        return wiOrgplanMMapper.selectWiOrgplanMByOrgCd(orgCd);
    }

    /**
     * 查询月机构限额水量及计划水量计算列表
     *
     * @param wiOrgplanM 月机构限额水量及计划水量计算
     * @return 月机构限额水量及计划水量计算
     */
    @Override
    public List<WiOrgplanM> selectWiOrgplanMList(WiOrgplanM wiOrgplanM) {
        return wiOrgplanMMapper.selectWiOrgplanMList(wiOrgplanM);
    }

    /**
     * 新增月机构限额水量及计划水量计算
     *
     * @param wiOrgplanM 月机构限额水量及计划水量计算
     * @return 结果
     */
    @Override
    public int insertWiOrgplanM(WiOrgplanM wiOrgplanM) {
        return wiOrgplanMMapper.insertWiOrgplanM(wiOrgplanM);
    }

    /**
     * 修改月机构限额水量及计划水量计算
     *
     * @param wiOrgplanM 月机构限额水量及计划水量计算
     * @return 结果
     */
    @Override
    public int updateWiOrgplanM(WiOrgplanM wiOrgplanM) {
        return wiOrgplanMMapper.updateWiOrgplanM(wiOrgplanM);
    }

    /**
     * 批量删除月机构限额水量及计划水量计算
     *
     * @param orgCd 需要删除的月机构限额水量及计划水量计算主键
     * @return 结果
     */
    @Override
    public int deleteWiOrgplanMByOrgCds(String orgCd, String planYm) {
        return wiOrgplanMMapper.deleteWiOrgplanMByOrgCds(orgCd, planYm);
    }

    /**
     * 删除月机构限额水量及计划水量计算信息
     *
     * @param orgCd 月机构限额水量及计划水量计算主键
     * @return 结果
     */
    @Override
    public int deleteWiOrgplanMByOrgCd(String orgCd) {
        return wiOrgplanMMapper.deleteWiOrgplanMByOrgCd(orgCd);
    }

    /**
     * 根据机构编码查询地块信息
     *
     * @param orgCd
     * @return
     */
    @Override
    public List<WiLandBVo> getWiLandBListByOrgCd(String year, String orgCd) {
        String orgCdQuery;
        HashMap<String, Object> addvAndOrgCodeInfo = BusinessUtils.getAddvAndOrgCodeInfo(orgCd);
        orgCdQuery = addvAndOrgCodeInfo.get("resCode") + "";
        log.info("供like查询的机构编码为 ： " + orgCdQuery);
        List<WiLandBVo> list = wiOrgplanMMapper.getWiLandBListByOrgCd(orgCdQuery);
        //遍历地块
        for (WiLandBVo vo : list) {
            //年度作物id
            String cropCd = vo.getCropCd();
            String CropNm = wiOrgplanMMapper.selcetCropNm(cropCd);
            //定义定额
            BigDecimal planVol = new BigDecimal("0");
            List<WiPeriodY> wiPeriodYList = wiPeriodYMapper.selectWiPeriodListbyCropAndCropCd(year, cropCd);
            //遍历周期定额
            for (WiPeriodY wiPeriodY : wiPeriodYList) {
                planVol = planVol.add(new BigDecimal(vo.getLandSize() + "").multiply(wiPeriodY.getPeriodVol()));
            }
            vo.setPlanVol(planVol);
            vo.setCropNm(CropNm);
        }
        return list;
    }

    /**
     * 汇总计划
     *
     * @param orgCd
     * @param year
     * @throws Exception
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public int setTenPlan(String orgCd, String year) throws Exception {
        /**返回数据定义 start*/
        ArrayList<HashMap<String, Object>> resList = new ArrayList<>();
        BigDecimal ten1;//上旬水量
        BigDecimal ten2;//中旬水量
        BigDecimal ten3;//下旬水量
        BigDecimal monthSum;//月水量
        /**返回数据定义 new*/
        List<WiLandBVo> WiLandBVoList = this.getWiLandBListByOrgCd(year, orgCd);
        //将所有地块按作物分组求面积和
        Map<String, Double> collect = WiLandBVoList.parallelStream().collect(Collectors.groupingBy(WiLandBVo::getCropCd,
                Collectors.summingDouble(s -> Double.valueOf(s.getLandSize() == null ? "0" : s.getLandSize() + ""))));
        //遍历12个月
        for (String monthStr : BusinessConstants.MONTHS) {
//            if (!monthStr.equals("02")) {
//                continue;
//            }
            //每月变量清零
            HashMap<String, Object> resMap = new HashMap<>();
            ten1 = new BigDecimal("0");//上旬水量
            ten2 = new BigDecimal("0");//中旬水量
            ten3 = new BigDecimal("0");//下旬水量
            monthSum = new BigDecimal("0");//月水量
            //遍历作物-地块面积和
            for (Map.Entry<String, Double> entry : collect.entrySet()) {
                log.info("作物代码：" + entry.getKey() + "=地块面积：" + entry.getValue());
                List<WiPeriodY> wiPeriodYList = wiPeriodYMapper.selectWiPeriodListbyCropAndCropCd(year, entry.getKey());
                //遍历周期定额
                for (WiPeriodY wiPeriodY : wiPeriodYList) {
                    for (HashMap<String, String> tensMap : BusinessConstants.TENSLIST) {
                        BigDecimal periodVol = wiPeriodY.getPeriodVol() == null ? new BigDecimal("0") : wiPeriodY.getPeriodVol();
                        String beginDate = DateUtils.dateTime(wiPeriodY.getBeginDate());
                        String endDate = DateUtils.dateTime(wiPeriodY.getEndDate());
                        String beginDate2 = year + "-" + monthStr + "-" + tensMap.get("tenStart");
                        String endDate2 = year + "-" + monthStr + "-" + tensMap.get("tenEnd");
                        //动态调整当月最后一天
                        if (tensMap.get("tenEnd").equals("31")) {
                            endDate2 = BusinessUtils.getMonthLastday(year, monthStr);
                        }
                        int i = BusinessUtils.differentDaysByMillisecond(wiPeriodY.getBeginDate(), wiPeriodY.getEndDate());
                        int days = BusinessUtils.getDays(beginDate, endDate, beginDate2, endDate2);
                        log.info("周期定额：" + beginDate + "=" + endDate);
                        log.info("旬分区：" + beginDate2 + "=" + endDate2);
                        log.info("包含天数：" + days);
                        log.info("周期定额包含天数：" + i + " 周期定额为：" + periodVol);
                        log.info(" 定额按比例计算结果：" + periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2));
                        log.info(" 地块旬定额水量：" + new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                        //上旬
                        if (TenEnum.TEN1.getCode().equals(tensMap.get("ten1"))) {
                            ten1 = ten1.add(new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                        }
                        //中旬
                        if (TenEnum.TEN2.getCode().equals(tensMap.get("ten2"))) {
                            ten2 = ten2.add(new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                        }
                        //下旬
                        if (TenEnum.TEN3.getCode().equals(tensMap.get("ten3"))) {
                            ten3 = ten3.add(new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                        }
                        monthSum = monthSum.add(new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                    }
                }
            }
            //将旬放入
            resMap.put("month", monthStr);
            resMap.put("ten1", ten1);
            resMap.put("ten2", ten2);
            resMap.put("ten3", ten3);
            resMap.put("monthSum", monthSum);
            resList.add(resMap);

            int i = insertWiOrgplanM(orgCd, year, monthStr, ten1, ten2, ten3, monthSum);
            if (i != 1) {
                throw new RuntimeException("汇总用水计划失败，请联系管理员~001");
            }
        }
        return 1;
    }

    /**
     * 汇总各级机构的逐月旬用水
     *
     * @param year
     * @param orgCd
     * @return
     */
    @Override
    public ArrayList<Object> getOrgPlanByPlanYmAndOrgCd(String year, String orgCd) {
        //该机构下所有旬计划
        String orgCdQuery;
        HashMap<String, Object> addvAndOrgCodeInfo = BusinessUtils.getAddvAndOrgCodeInfo(orgCd);
        orgCdQuery = addvAndOrgCodeInfo.get("resCode") + "";
        List<WiOrgplanM> orgPlanByPlanYmAndOrgCdList = wiOrgplanMMapper.getOrgPlanByPlanYmAndOrgCd(year, orgCdQuery);
        //将计划按planYm分组把计划用水求和
        Map<String, Double> MonthSumCollect = orgPlanByPlanYmAndOrgCdList.parallelStream().collect(Collectors.groupingBy(WiOrgplanM::getPlanYm,
                Collectors.summingDouble(s -> Double.parseDouble(s.getMonPlan() + ""))));
//        for (Map.Entry<String, Double> entry : MonthSumCollect.entrySet()) {
//            log.info(entry.getKey() + "=" + entry.getValue());
//        }
        //上旬计划和
        Map<String, Double> ten1Collect = orgPlanByPlanYmAndOrgCdList.parallelStream().collect(Collectors.groupingBy(WiOrgplanM::getPlanYm,
                Collectors.summingDouble(s -> Double.parseDouble(s.getFirstPlan() + ""))));
//        for (Map.Entry<String, Double> entry : ten1Collect.entrySet()) {
//            log.info(entry.getKey() + "=" + entry.getValue());
//        }
        //中旬计划和
        Map<String, Double> ten2Collect = orgPlanByPlanYmAndOrgCdList.parallelStream().collect(Collectors.groupingBy(WiOrgplanM::getPlanYm,
                Collectors.summingDouble(s -> Double.parseDouble(s.getSecondPlan() + ""))));
//        for (Map.Entry<String, Double> entry : ten2Collect.entrySet()) {
//            log.info(entry.getKey() + "=" + entry.getValue());
//        }
        //下旬计划和
        Map<String, Double> ten3Collect = orgPlanByPlanYmAndOrgCdList.parallelStream().collect(Collectors.groupingBy(WiOrgplanM::getPlanYm,
                Collectors.summingDouble(s -> Double.parseDouble(s.getThirdPlan() + ""))));
//        for (Map.Entry<String, Double> entry : ten3Collect.entrySet()) {
//            log.info(entry.getKey() + "=" + entry.getValue());
//        }
        //整理页面数据格式 0	[ "2023", "春灌", "2月", "上旬", "0", "0" ]
        ArrayList<Object> res = new ArrayList<>();
        for (String monthStr : BusinessConstants.MONTHS) {
            if (monthStr.equals("01")) {
                continue;
            }
            //上中下旬
            for (HashMap<String, String> tensMap : BusinessConstants.TENSLIST) {
                ArrayList<String> planInfo = new ArrayList<>();
                planInfo.add(year);
                if (monthStr.equals("02") || monthStr.equals("03") || monthStr.equals("04")) {
                    planInfo.add("春灌");
                }
                if (monthStr.equals("05") || monthStr.equals("06") || monthStr.equals("07") || monthStr.equals("08")) {
                    planInfo.add("夏灌");
                }
                if (monthStr.equals("09") || monthStr.equals("10") || monthStr.equals("11") || monthStr.equals("12")) {
                    planInfo.add("冬灌");
                }
                planInfo.add(Integer.parseInt(monthStr) + "月");
                if ("ten1".equals(tensMap.get("ten1"))) {
                    planInfo.add("上旬");
                    planInfo.add(ten1Collect.get(year + monthStr) + "");
                }
                if ("ten2".equals(tensMap.get("ten2"))) {
                    planInfo.add("中旬");
                    planInfo.add(ten2Collect.get(year + monthStr) + "");
                }
                if ("ten3".equals(tensMap.get("ten3"))) {
                    planInfo.add("下旬");
                    planInfo.add(ten3Collect.get(year + monthStr) + "");
                }
                res.add(planInfo);
            }
            ArrayList<String> planInfo = new ArrayList<>();
            planInfo.add(year);
            if (monthStr.equals("02") || monthStr.equals("03") || monthStr.equals("04")) {
                planInfo.add("春灌");
            }
            if (monthStr.equals("05") || monthStr.equals("06") || monthStr.equals("07") || monthStr.equals("08")) {
                planInfo.add("夏灌");
            }
            if (monthStr.equals("09") || monthStr.equals("10") || monthStr.equals("11") || monthStr.equals("12")) {
                planInfo.add("冬灌");
            }
            planInfo.add(Integer.parseInt(monthStr) + "月");
            planInfo.add("月总量");
            planInfo.add(MonthSumCollect.get(year + monthStr) + "");
            res.add(planInfo);
        }
        return res;

    }

    /**
     * 获取机构年度用水计划
     *
     * @param year
     * @param orgCd
     * @return
     */
    @Override
    public ArrayList<Object> getOrgPlanYear(String year, String orgCd) {
        ArrayList<Object> res = new ArrayList<>();
        String orgCdQuery;
        HashMap<String, Object> addvAndOrgCodeInfo = BusinessUtils.getAddvAndOrgCodeInfo(orgCd);
        orgCdQuery = addvAndOrgCodeInfo.get("resCode") + "";
        //查询
        List<WiOrgplanM> orgPlanYearList = wiOrgplanMMapper.getOrgPlanYear(year, orgCdQuery);
        //按机构编码汇总出年用水计划
        Map<String, Double> yearSumCollect = orgPlanYearList.parallelStream().collect(Collectors.groupingBy(WiOrgplanM::getOrgCd,
                Collectors.summingDouble(s -> Double.parseDouble(s.getMonPlan() + ""))));
        for (Map.Entry<String, Double> entry : yearSumCollect.entrySet()) {
            if (orgCd.equals(entry.getKey())) {
                continue;
            }
            HashMap<String, Object> monthVolMap = new HashMap<>();
            monthVolMap.put("orgCd", entry.getKey());

            //查询机构名称 start
            String orgNm = wiOrgplanMMapper.getOrgNm(entry.getKey());
            monthVolMap.put("orgNm", orgNm);
            //查询机构名称 end

            //过滤出机构当年计划
            List<WiOrgplanM> collect = orgPlanYearList.stream().filter(vo -> vo.getOrgCd().equals(entry.getKey())).filter(vo -> vo.getPlanYm().substring(0, 4).equals(year)).collect(Collectors.toList());
            for (WiOrgplanM wiOrgplanM : collect) {
                for (String monthStr : BusinessConstants.MONTHS) {
                    if ((year + monthStr).equals(wiOrgplanM.getPlanYm())) {
                        monthVolMap.put("month" + monthStr, wiOrgplanM.getMonPlan());
                    }
                }
            }
            monthVolMap.put("sum", entry.getValue());
            res.add(monthVolMap);
        }
        return res;
    }

    /**
     * 显示各级水管机构计划用水和实测水量的对比
     *
     * @param year
     * @param orgCd
     */
    @Override
    public HashMap<String, Object> orgVolAnalys(String year, String orgCd) {
        HashMap<String, Object> res = new HashMap<>();
        String orgCdQuery;
        HashMap<String, Object> addvAndOrgCodeInfo = BusinessUtils.getAddvAndOrgCodeInfo(orgCd);
        orgCdQuery = addvAndOrgCodeInfo.get("resCode") + "";
        //查询
        List<WiOrgplanM> orgPlanYearList = wiOrgplanMMapper.getOrgPlanYear(year, orgCdQuery);
        //12个月的月配水量
        TreeMap<String, Object> monthVolMap = new TreeMap<>();
        for (String monthStr : BusinessConstants.MONTHS) {
            BigDecimal monSumCroVol = new BigDecimal("0");
            for (WiOrgplanM wiOrgplanM : orgPlanYearList) {
                if ((year + monthStr).equals(wiOrgplanM.getPlanYm())) {
                    monSumCroVol = monSumCroVol.add(wiOrgplanM.getMonPlan());
                }
                monthVolMap.put("month" + monthStr, monSumCroVol);
            }
        }
        List<Object> monthVolList = new ArrayList<>(monthVolMap.values());
        res.put("plan", monthVolList);

        TreeMap<String, Object> accVolMap = new TreeMap<>();
        //根据断面查测站 测站月水量数据
        List<WrStatvolM> wrStatvolMList = wiOrgplanMMapper.getWrStatvolMByYearAndOrgCd(year, orgCdQuery);
        //12个月的月实际水量
        for (String monthStr : BusinessConstants.MONTHS) {
            BigDecimal monSumCroVol = new BigDecimal("0");
            for (WrStatvolM wrStatvolM : wrStatvolMList) {
                if ((year + monthStr).equals(wrStatvolM.getStatMon())) {
                    monSumCroVol = monSumCroVol.add(wrStatvolM.getMonVol().multiply(new BigDecimal("10000")));
                }
                accVolMap.put("month" + monthStr, monSumCroVol);
            }
        }
        List<Object> accVolList = new ArrayList<>(accVolMap.values());
        res.put("acc", accVolList);

        return res;
    }

    /**
     * 导入上一年用水计划
     *
     * @return
     */
    @Override
    public List<WiOrgplanM> importLastYearPlan(String year, String orgCd) {
        List<WiOrgplanM> orgPlanByPlanYmAndOrgCdList = wiOrgplanMMapper.getOrgPlanByPlanYmAndOrgCd(year, orgCd);
        if (orgPlanByPlanYmAndOrgCdList.size() == 0) {
            return orgPlanByPlanYmAndOrgCdList;
        } else {
            for (WiOrgplanM vo : orgPlanByPlanYmAndOrgCdList) {
                wiOrgplanMMapper.deleteWiOrgplanMByOrgCds(orgCd, (Integer.parseInt(year) + 1) + vo.getPlanYm().substring(4, 6));
                WiOrgplanM wiOrgplanM = new WiOrgplanM();
                wiOrgplanM.setOrgCd(orgCd);
                wiOrgplanM.setPlanYm((Integer.parseInt(year) + 1) + vo.getPlanYm().substring(4, 6));

                wiOrgplanM.setFirstPlan(vo.getFirstPlan());
                wiOrgplanM.setFirstCtrl(vo.getFirstCtrl());
                wiOrgplanM.setSecondPlan(vo.getSecondPlan());
                wiOrgplanM.setSecondCtrl(vo.getSecondCtrl());
                wiOrgplanM.setThirdPlan(vo.getThirdPlan());
                wiOrgplanM.setThirdCtrl(vo.getThirdCtrl());
                wiOrgplanM.setMonPlan(vo.getMonPlan());
                wiOrgplanM.setMonCtrl(vo.getMonCtrl());
                //操作人相关信息
                wiOrgplanM.setOperDate(new Date());
                wiOrgplanM.setLastId(SecurityUtils.getUserId() + "");
                wiOrgplanMMapper.insertWiOrgplanM(wiOrgplanM);

            }
            return wiOrgplanMMapper.getOrgPlanByPlanYmAndOrgCd((Integer.parseInt(year) + 1) + "", orgCd);
        }
    }

    private int insertWiOrgplanM(String orgCd, String year, String monthStr, BigDecimal ten1, BigDecimal ten2, BigDecimal ten3, BigDecimal monthSum) {
        WiOrgplanM wiOrgplanM = new WiOrgplanM();
        wiOrgplanM.setOrgCd(orgCd);
        wiOrgplanM.setPlanYm(year + monthStr);
        //判断是否已经存在计划，若存在则删除后重新添加汇总数据
        List<WiOrgplanM> wiOrgplanMS = wiOrgplanMMapper.selectWiOrgplanMList(wiOrgplanM);
        if (wiOrgplanMS.size() > 0) {
            wiOrgplanMMapper.deleteWiOrgplanMByOrgCds(orgCd, year + monthStr);
        }
        wiOrgplanM.setFirstPlan(ten1);
        wiOrgplanM.setFirstCtrl(ten1);
        wiOrgplanM.setSecondPlan(ten2);
        wiOrgplanM.setSecondCtrl(ten2);
        wiOrgplanM.setThirdPlan(ten3);
        wiOrgplanM.setThirdCtrl(ten3);
        wiOrgplanM.setMonPlan(monthSum);
        wiOrgplanM.setMonCtrl(monthSum);
        //操作人相关信息
        wiOrgplanM.setOperDate(new Date());
        wiOrgplanM.setLastId(SecurityUtils.getUserId() + "");

        return wiOrgplanMMapper.insertWiOrgplanM(wiOrgplanM);
    }
}
